home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / Main.bin / NumberFormat.java < prev    next >
Text File  |  1998-09-22  |  21KB  |  544 lines

  1. /*
  2.  * @(#)NumberFormat.java    1.35 98/02/02
  3.  *
  4.  * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved
  5.  * (C) Copyright IBM Corp. 1996 - All Rights Reserved
  6.  *
  7.  * Portions copyright (c) 1996-1997 Sun Microsystems, Inc. All Rights Reserved.
  8.  *
  9.  *   The original version of this source code and documentation is copyrighted
  10.  * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  11.  * materials are provided under terms of a License Agreement between Taligent
  12.  * and Sun. This technology is protected by multiple US and International
  13.  * patents. This notice and attribution to Taligent may not be removed.
  14.  *   Taligent is a registered trademark of Taligent, Inc.
  15.  *
  16.  * Permission to use, copy, modify, and distribute this software
  17.  * and its documentation for NON-COMMERCIAL purposes and without
  18.  * fee is hereby granted provided that this copyright notice
  19.  * appears in all copies. Please refer to the file "copyright.html"
  20.  * for further important copyright and licensing information.
  21.  *
  22.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  23.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  24.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  25.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  26.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  27.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  28.  *
  29.  */
  30.  
  31. package java.text;
  32. import java.util.Locale;
  33. import java.util.ResourceBundle;
  34. import java.text.resources.*;
  35. import java.util.Hashtable;
  36.  
  37. /**
  38.  * <code>NumberFormat</code> is the abstract base class for all number
  39.  * formats. This class provides the interface for formatting and parsing
  40.  * numbers. <code>NumberFormat</code> also provides methods for determining
  41.  * which locales have number formats, and what their names are.
  42.  *
  43.  * <p>
  44.  * <code>NumberFormat</code> helps you to format and parse numbers for any locale.
  45.  * Your code can be completely independent of the locale conventions for
  46.  * decimal points, thousands-separators, or even the particular decimal
  47.  * digits used, or whether the number format is even decimal.
  48.  *
  49.  * <p>
  50.  * To format a number for the current Locale, use one of the factory
  51.  * class methods:
  52.  * <blockquote>
  53.  * <pre>
  54.  *  myString = NumberFormat.getInstance().format(myNumber);
  55.  * </pre>
  56.  * </blockquote>
  57.  * If you are formatting multiple numbers, it is
  58.  * more efficient to get the format and use it multiple times so that
  59.  * the system doesn't have to fetch the information about the local
  60.  * language and country conventions multiple times.
  61.  * <blockquote>
  62.  * <pre>
  63.  * NumberFormat nf = NumberFormat.getInstance();
  64.  * for (int i = 0; i < a.length; ++i) {
  65.  *     output.println(nf.format(myNumber[i]) + "; ");
  66.  * }
  67.  * </pre>
  68.  * </blockquote>
  69.  * To format a number for a different Locale, specify it in the
  70.  * call to <code>getInstance</code>.
  71.  * <blockquote>
  72.  * <pre>
  73.  * NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH);
  74.  * </pre>
  75.  * </blockquote>
  76.  * You can also use a <code>NumberFormat</code> to parse numbers:
  77.  * <blockquote>
  78.  * <pre>
  79.  * myNumber = nf.parse(myString);
  80.  * </pre>
  81.  * </blockquote>
  82.  * Use <code>getInstance</code> or <code>getNumberInstance</code> to get the
  83.  * normal number format. Use <code>getCurrencyInstance</code> to get the
  84.  * currency number format. And use <code>getPercentInstance</code> to get a
  85.  * format for displaying percentages. With this format, a fraction like
  86.  * 0.53 is displayed as 53%.
  87.  *
  88.  * <p>
  89.  * You can also control the display of numbers with such methods as
  90.  * <code>setMinimumFractionDigits</code>.
  91.  * If you want even more control over the format or parsing,
  92.  * or want to give your users more control,
  93.  * you can try casting the <code>NumberFormat</code> you get from the factory methods
  94.  * to a <code>DecimalNumberFormat</code>. This will work for the vast majority
  95.  * of locales; just remember to put it in a <code>try</code> block in case you
  96.  * encounter an unusual one.
  97.  *
  98.  * <p>
  99.  * NumberFormat and DecimalFormat are designed such that some controls
  100.  * work for formatting and others work for parsing.  The following is
  101.  * the detailed description for each these control methods,
  102.  * <p>
  103.  * setParseIntegerOnly : only affects parsing, e.g.
  104.  * if true,  "3456.78" -> 3456 (and leaves the parse position just after index 6)
  105.  * if false, "3456.78" -> 3456.78 (and leaves the parse position just after index 8)
  106.  * This is independent of formatting.  If you want to not show a decimal point
  107.  * where there might be no digits after the decimal point, use
  108.  * setDecimalSeparatorAlwaysShown.
  109.  * <p>
  110.  * setDecimalSeparatorAlwaysShown : only affects formatting, and only where
  111.  * there might be no digits after the decimal point, such as with a pattern
  112.  * like "#,##0.##", e.g.,
  113.  * if true,  3456.00 -> "3,456."
  114.  * if false, 3456.00 -> "3456"
  115.  * This is independent of parsing.  If you want parsing to stop at the decimal
  116.  * point, use setParseIntegerOnly.
  117.  *
  118.  * <p>
  119.  * You can also use forms of the <code>parse</code> and <code>format</code>
  120.  * methods with <code>ParsePosition</code> and <code>FieldPosition</code> to
  121.  * allow you to:
  122.  * <ul>
  123.  * <li> progressively parse through pieces of a string
  124.  * <li> align the decimal point and other areas
  125.  * </ul>
  126.  * For example, you can align numbers in two ways:
  127.  * <ol>
  128.  * <li> If you are using a monospaced font with spacing for alignment,
  129.  *      you can pass the <code>FieldPosition</code> in your format call, with
  130.  *      <code>field</code> = <code>INTEGER_FIELD</code>. On output,
  131.  *      <code>getEndIndex</code> will be set to the offset between the
  132.  *      last character of the integer and the decimal. Add
  133.  *      (desiredSpaceCount - getEndIndex) spaces at the front of the string.
  134.  *
  135.  * <li> If you are using proportional fonts,
  136.  *      instead of padding with spaces, measure the width
  137.  *      of the string in pixels from the start to <code>getEndIndex</code>.
  138.  *      Then move the pen by
  139.  *      (desiredPixelWidth - widthToAlignmentPoint) before drawing the text.
  140.  *      It also works where there is no decimal, but possibly additional
  141.  *      characters at the end, e.g. with parentheses in negative
  142.  *      numbers: "(12)" for -12.
  143.  * </ol>
  144.  *
  145.  * @see          DecimalFormat
  146.  * @see          ChoiceFormat
  147.  * @version      1.22 29 Jan 1997
  148.  * @author       Mark Davis
  149.  * @author       Helena Shih
  150.  */
  151. public abstract class NumberFormat extends Format implements java.lang.Cloneable {
  152.  
  153.     /**
  154.      * Field constant used to construct a FieldPosition object. Signifies that
  155.      * the position of the integer part of a formatted number should be returned.
  156.      * @see java.text.FieldPosition
  157.      */
  158.     public static final int INTEGER_FIELD = 0;
  159.  
  160.     /**
  161.      * Field constant used to construct a FieldPosition object. Signifies that
  162.      * the position of the fraction part of a formatted number should be returned.
  163.      * @see java.text.FieldPosition
  164.      */
  165.     public static final int FRACTION_FIELD = 1;
  166.  
  167.     public final StringBuffer format(Object number,
  168.                                      StringBuffer toAppendTo,
  169.                                      FieldPosition pos)
  170.     {
  171.         if (number instanceof Double || number instanceof Float) {
  172.             return format(((Number)number).doubleValue(), toAppendTo, pos);
  173.         }
  174.         else if (number instanceof Number) {
  175.             return format(((Number)number).longValue(), toAppendTo, pos);
  176.         }
  177.         else {
  178.             throw new IllegalArgumentException("Cannot format given Object as a Number");
  179.         }
  180.     }
  181.  
  182.     public final Object parseObject(String source,
  183.                                     ParsePosition parsePosition)
  184.     {
  185.         return parse(source, parsePosition);
  186.     }
  187.  
  188.    /**
  189.      * Specialization of format.
  190.      * @see java.text.Format#format
  191.      */
  192.     public final String format (double number) {
  193.         return format(number,new StringBuffer(),
  194.                       new FieldPosition(0)).toString();
  195.     }
  196.  
  197.    /**
  198.      * Specialization of format.
  199.      * @see java.text.Format#format
  200.      */
  201.     public final String format (long number) {
  202.         return format(number,new StringBuffer(),
  203.                       new FieldPosition(0)).toString();
  204.     }
  205.  
  206.    /**
  207.      * Specialization of format.
  208.      * @see java.text.Format#format
  209.      */
  210.     public abstract StringBuffer format(double number,
  211.                                         StringBuffer toAppendTo,
  212.                                         FieldPosition pos);
  213.  
  214.    /**
  215.      * Specialization of format.
  216.      * @see java.text.Format#format
  217.      */
  218.     public abstract StringBuffer format(long number,
  219.                                         StringBuffer toAppendTo,
  220.                                         FieldPosition pos);
  221.  
  222.    /**
  223.      * Returns a Long if possible (e.g. within range [Long.MIN_VALUE,
  224.      * Long.MAX_VALUE], and with no decimals), otherwise a Double.
  225.      * If IntegerOnly is set, will stop at a decimal
  226.      * point (or equivalent; e.g. for rational numbers "1 2/3", will stop
  227.      * after the 1).
  228.      * Does not throw an exception; if no object can be parsed, index is
  229.      * unchanged!
  230.      * @see java.text.NumberFormat#isParseIntegerOnly
  231.      * @see java.text.Format#parseObject
  232.      */
  233.     public abstract Number parse(String text, ParsePosition parsePosition);
  234.  
  235.     /**
  236.      * Convenience method.
  237.      *
  238.      * @exception ParseException if the specified string is invalid.
  239.      * @see #format
  240.      */
  241.     public Number parse(String text) throws ParseException {
  242.         ParsePosition parsePosition = new ParsePosition(0);
  243.         Number result = parse(text, parsePosition);
  244.         if (parsePosition.index == 0) {
  245.             throw new ParseException("Unparseable number: \"" + text + "\"", 0);
  246.         }
  247.         return result;
  248.     }
  249.  
  250.     /**
  251.      * Returns true if this format will parse numbers as integers only.
  252.      * For example in the English locale, with ParseIntegerOnly true, the
  253.      * string "1234." would be parsed as the integer value 1234 and parsing
  254.      * would stop at the "." character.  Of course, the exact format accepted
  255.      * by the parse operation is locale dependant and determined by sub-classes
  256.      * of NumberFormat.
  257.      */
  258.     public boolean isParseIntegerOnly() {
  259.         return parseIntegerOnly;
  260.     }
  261.  
  262.     /**
  263.      * Sets whether or not numbers should be parsed as integers only.
  264.      * @see #isParseIntegerOnly
  265.      */
  266.     public void setParseIntegerOnly(boolean value) {
  267.         parseIntegerOnly = value;
  268.     }
  269.  
  270.     //============== Locale Stuff =====================
  271.  
  272.     /**
  273.      * Returns the default number format for the current default locale.
  274.      * The default format is one of the styles provided by the other
  275.      * factory methods: getNumberInstance, getCurrencyInstance or getPercentInstance.
  276.      * Exactly which one is locale dependant.
  277.      */
  278.     public final static NumberFormat getInstance() {
  279.         return getInstance(Locale.getDefault(), NUMBERSTYLE);
  280.     }
  281.  
  282.     /**
  283.      * Returns the default number format for the specified locale.
  284.      * The default format is one of the styles provided by the other
  285.      * factory methods: getNumberInstance, getCurrencyInstance or getPercentInstance.
  286.      * Exactly which one is locale dependant.
  287.      */
  288.     public static NumberFormat getInstance(Locale inLocale) {
  289.         return getInstance(inLocale, NUMBERSTYLE);
  290.     }
  291.  
  292.     /**
  293.      * Returns a general-purpose number format for the current default locale.
  294.      */
  295.     public final static NumberFormat getNumberInstance() {
  296.         return getInstance(Locale.getDefault(), NUMBERSTYLE);
  297.     }
  298.  
  299.     /**
  300.      * Returns a general-purpose number format for the specified locale.
  301.      */
  302.     public static NumberFormat getNumberInstance(Locale inLocale) {
  303.         return getInstance(inLocale, NUMBERSTYLE);
  304.     }
  305.  
  306.     /**
  307.      * Returns a currency format for the current default locale.
  308.      */
  309.     public final static NumberFormat getCurrencyInstance() {
  310.         return getInstance(Locale.getDefault(), CURRENCYSTYLE);
  311.     }
  312.  
  313.     /**
  314.      * Returns a currency format for the specified locale.
  315.      */
  316.     public static NumberFormat getCurrencyInstance(Locale inLocale) {
  317.         return getInstance(inLocale, CURRENCYSTYLE);
  318.     }
  319.  
  320.     /**
  321.      * Returns a percentage format for the current default locale.
  322.      */
  323.     public final static NumberFormat getPercentInstance() {
  324.         return getInstance(Locale.getDefault(), PERCENTSTYLE);
  325.     }
  326.  
  327.     /**
  328.      * Returns a percentage format for the specified locale.
  329.      */
  330.     public static NumberFormat getPercentInstance(Locale inLocale) {
  331.         return getInstance(inLocale, PERCENTSTYLE);
  332.     }
  333.  
  334.     /**
  335.      * Returns a scientific format for the current default locale.
  336.      */
  337.     /*public*/ final static NumberFormat getScientificInstance() {
  338.         return getInstance(Locale.getDefault(), SCIENTIFICSTYLE);
  339.     }
  340.  
  341.     /**
  342.      * Returns a scientific format for the specified locale.
  343.      */
  344.     /*public*/ static NumberFormat getScientificInstance(Locale inLocale) {
  345.         return getInstance(inLocale, SCIENTIFICSTYLE);
  346.     }
  347.  
  348.  
  349.     /**
  350.      * Get the set of Locales for which NumberFormats are installed
  351.      * @return available locales
  352.      */
  353.     public static Locale[] getAvailableLocales() {
  354.         return LocaleData.getAvailableLocales("NumberPatterns");
  355.     }
  356.  
  357.     /**
  358.      * Overrides hashCode
  359.      */
  360.     public int hashCode() {
  361.         return maxIntegerDigits * 37 + maxFractionDigits;
  362.         // just enough fields for a reasonable distribution
  363.     }
  364.  
  365.     /**
  366.      * Overrides equals
  367.      */
  368.     public boolean equals(Object obj) {
  369.         if (obj == null) return false;
  370.         if (this == obj)
  371.             return true;
  372.         if (getClass() != obj.getClass())
  373.             return false;
  374.         NumberFormat other = (NumberFormat) obj;
  375.         return (maxIntegerDigits == other.maxIntegerDigits
  376.             && minIntegerDigits == other.minIntegerDigits
  377.             && maxFractionDigits == other.maxFractionDigits
  378.             && minFractionDigits == other.minFractionDigits
  379.             && groupingUsed == other.groupingUsed
  380.             && parseIntegerOnly == other.parseIntegerOnly);
  381.     }
  382.  
  383.     /**
  384.      * Overrides Cloneable
  385.      */
  386.     public Object clone()
  387.     {
  388.         NumberFormat other = (NumberFormat) super.clone();
  389.         return other;
  390.     }
  391.  
  392.     /**
  393.      * Returns true if grouping is used in this format. For example, in the
  394.      * English locale, with grouping on, the number 1234567 might be formatted
  395.      * as "1,234,567". The grouping separator as well as the size of each group
  396.      * is locale dependant and is determined by sub-classes of NumberFormat.
  397.      * @see #setGroupingUsed
  398.      */
  399.     public boolean isGroupingUsed() {
  400.         return groupingUsed;
  401.     }
  402.  
  403.     /**
  404.      * Set whether or not grouping will be used in this format.
  405.      * @see #isGroupingUsed
  406.      */
  407.     public void setGroupingUsed(boolean newValue) {
  408.         groupingUsed = newValue;
  409.     }
  410.  
  411.     /**
  412.      * Returns the maximum number of digits allowed in the integer portion of a
  413.      * number.
  414.      * @see #setMaximumIntegerDigits
  415.      */
  416.     public int getMaximumIntegerDigits() {
  417.         return maxIntegerDigits;
  418.     }
  419.  
  420.     /**
  421.      * Sets the maximum number of digits allowed in the integer portion of a
  422.      * number. maximumIntegerDigits must be >= minimumIntegerDigits.  If the
  423.      * new value for maximumIntegerDigits is less than the current value
  424.      * of minimumIntegerDigits, then minimumIntegerDigits will also be set to
  425.      * the new value.
  426.  
  427.      * @see #getMaximumIntegerDigits
  428.      */
  429.     public void setMaximumIntegerDigits(int newValue) {
  430.         maxIntegerDigits = (byte) Math.max(0,Math.min(newValue,308));
  431.         if (minIntegerDigits > maxIntegerDigits)
  432.             minIntegerDigits = maxIntegerDigits;
  433.     }
  434.  
  435.     /**
  436.      * Returns the minimum number of digits allowed in the integer portion of a
  437.      * number.
  438.      * @see #setMinimumIntegerDigits
  439.      */
  440.     public int getMinimumIntegerDigits() {
  441.         return minIntegerDigits;
  442.     }
  443.  
  444.     /**
  445.      * Sets the minimum number of digits allowed in the integer portion of a
  446.      * number. minimumIntegerDigits must be <= maximumIntegerDigits.  If the
  447.      * new value for minimumIntegerDigits exceeds the current value
  448.      * of maximumIntegerDigits, then maximumIntegerDigits will also be set to
  449.      * the new value
  450.      * @see #getMinimumIntegerDigits
  451.      */
  452.     public void setMinimumIntegerDigits(int newValue) {
  453.         minIntegerDigits = (byte) Math.max(0,Math.min(newValue,127));
  454.         if (minIntegerDigits > maxIntegerDigits)
  455.             maxIntegerDigits = minIntegerDigits;
  456.     }
  457.  
  458.     /**
  459.      * Returns the maximum number of digits allowed in the fraction portion of a
  460.      * number.
  461.      * @see #setMaximumFractionDigits
  462.      */
  463.     public int getMaximumFractionDigits() {
  464.         return maxFractionDigits;
  465.     }
  466.  
  467.     /**
  468.      * Sets the maximum number of digits allowed in the fraction portion of a
  469.      * number. maximumFractionDigits must be >= minimumFractionDigits.  If the
  470.      * new value for maximumFractionDigits is less than the current value
  471.      * of minimumFractionDigits, then minimumFractionDigits will also be set to
  472.      * the new value.
  473.      * @see #getMaximumFractionDigits
  474.      */
  475.     public void setMaximumFractionDigits(int newValue) {
  476.         maxFractionDigits = (byte) Math.max(0,Math.min(newValue,340));
  477.         if (maxFractionDigits < minFractionDigits)
  478.             minFractionDigits = maxFractionDigits;
  479.     }
  480.  
  481.     /**
  482.      * Returns the minimum number of digits allowed in the fraction portion of a
  483.      * number.
  484.      * @see #setMinimumFractionDigits
  485.      */
  486.     public int getMinimumFractionDigits() {
  487.         return minFractionDigits;
  488.     }
  489.  
  490.     /**
  491.      * Sets the minimum number of digits allowed in the fraction portion of a
  492.      * number. minimumFractionDigits must be <= maximumFractionDigits.  If the
  493.      * new value for minimumFractionDigits exceeds the current value
  494.      * of maximumFractionDigits, then maximumIntegerDigits will also be set to
  495.      * the new value
  496.      * @see #getMinimumFractionDigits
  497.      */
  498.     public void setMinimumFractionDigits(int newValue) {
  499.         minFractionDigits = (byte) Math.max(0,Math.min(newValue,127));
  500.         if (maxFractionDigits < minFractionDigits)
  501.             maxFractionDigits = minFractionDigits;
  502.     }
  503.  
  504.     // =======================privates===============================
  505.  
  506.     private static NumberFormat getInstance(Locale desiredLocale,
  507.                                            int choice)
  508.     {
  509.     /* try the cache first */
  510.     String[] numberPatterns = (String[])cachedLocaleData.get(desiredLocale);
  511.     if (numberPatterns == null) { /* cache miss */
  512.         ResourceBundle resource = ResourceBundle.getBundle
  513.         ("java.text.resources.LocaleElements", desiredLocale);
  514.         numberPatterns = resource.getStringArray("NumberPatterns");
  515.         /* update cache */
  516.         cachedLocaleData.put(desiredLocale, numberPatterns);
  517.     }
  518.  
  519.         return new DecimalFormat(numberPatterns[choice],
  520.                                  new DecimalFormatSymbols(desiredLocale));
  521.     }
  522.  
  523.     /**
  524.      * Cache to hold the NumberPatterns of a Locale.
  525.      */
  526.     private static final Hashtable cachedLocaleData = new Hashtable(3);
  527.  
  528.     // Constants used by factory methods to specify a style of format.
  529.     private static final int NUMBERSTYLE = 0;
  530.     private static final int CURRENCYSTYLE = 1;
  531.     private static final int PERCENTSTYLE = 2;
  532.     private static final int SCIENTIFICSTYLE = 3;
  533.  
  534.     private boolean groupingUsed = true;
  535.     private byte    maxIntegerDigits = 40;
  536.     private byte    minIntegerDigits = 1;
  537.     private byte    maxFractionDigits = 3;    // invariant, >= minFractionDigits
  538.     private byte    minFractionDigits = 0;
  539.     private boolean parseIntegerOnly = false;
  540.     // Removed "implements Cloneable" clause.  Needs to update serialization
  541.     // ID for backward compatibility.
  542.     static final long serialVersionUID = -2308460125733713944L;
  543. }
  544.